﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using Caliburn.Micro;
using Scrabble.Model;
using Scrabble.Tasks;

namespace Scrabble.ViewModels
{
    [Export(typeof(SelectPlayersViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
    public sealed class SelectPlayersViewModel : Screen, IDialog
    {
        private readonly ObservableCollection<string> _namesOfPlayers = new ObservableCollection<string>();
        private string _playerName;
        private int _selectedIndex;

        public event EventHandler<DialogResultCompletionEventArgs> Completed;

        public SelectPlayersViewModel()
        {
            DisplayName = "Select Players";
        }

        public IList<string> NamesOfPlayers
        {
            get { return _namesOfPlayers; }
            set
            {
                if (value == NamesOfPlayers) return;

                RemoveAll();

                if (value == null) return;

                foreach (var name in value.Where(IsNameAcceptable))
                    AddName(name);
            }
        }

        public string PlayerName
        {
            get { return _playerName; }
            set
            {
                if (value == PlayerName) return;

                _playerName = value;

                NotifyOfPropertyChange(() => PlayerName);
                NotifyOfPropertyChange(() => CanAdd);
            }
        }

        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set
            {
                if (value == SelectedIndex) return;

                _selectedIndex = value;
                Refresh();
            }
        }

        public bool CanAddMorePlayers
        {
            get { return _namesOfPlayers.Count < Game.MaxPlayers; }
        }

        public bool CanMoveUp
        {
            get { return SelectedIndex > 0; }
        }

        public void MoveUp()
        {
            MoveName(SelectedIndex, SelectedIndex - 1);
        }

        public bool CanMoveDown
        {
            get { return SelectedIndex >= 0 && SelectedIndex + 1 < _namesOfPlayers.Count; }
        }

        public void MoveDown()
        {
            MoveName(SelectedIndex, SelectedIndex + 1);
        }

        public bool CanAdd
        {
            get { return CanAddMorePlayers && IsNameAcceptable(PlayerName);  }
        }

        public void Add()
        {
            AddName(PlayerName);
            PlayerName = String.Empty;

            Refresh();
        }

        public bool CanRemove
        {
            get { return SelectedIndex >= 0; }
        }

        public void Remove()
        {
            _namesOfPlayers.RemoveAt(SelectedIndex);
            Refresh();
        }

        public bool CanRemoveAll
        {
            get { return _namesOfPlayers.Any(); }
        }

        public void RemoveAll()
        {
            _namesOfPlayers.Clear();
            Refresh();
        }

        public bool CanOpen
        {
            get { return _namesOfPlayers.Any(); }
        }

        public void Open()
        {
            Completed(this, new DialogResultCompletionEventArgs { DialogResult = true });
        }

        private void MoveName(int oldIndex, int newIndex)
        {
            _namesOfPlayers.Move(oldIndex, newIndex);
            NotifyOfPropertyChange(() => CanMoveUp);
            NotifyOfPropertyChange(() => CanMoveDown);
        }

        private void AddName(string name)
        {
            _namesOfPlayers.Add(name.Trim());
        }

        private static bool IsNameAcceptable(string name)
        {
            return !String.IsNullOrWhiteSpace(name);
        }
    }
}
